/*
 * Copyright (c) 2013-2018 上海汇数数据. All rights reserved.
 * @(#) JsonOperator.java 2018-08-06 16:32
 */

package cn.jh.common.core.json;

import cn.jh.common.core.reflect.Generics;
import org.jetbrains.annotations.Contract;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Type;
import java.nio.file.OpenOption;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * @author Fuchun
 * @since 1.0
 */
public interface JsonOperator {

    /**
     * 将指定的对象序列化JSON格式字符串。
     *
     * @param object 要序列化的对象。
     * @return 返回指定对象的JSON格式字符串。
     * @throws JsonParseException 如果序列化发生错误。
     */
    default String toJSONString(Object object) {
        return toJSONString(object, false);
    }

    default String toPrettyJSONString(Object object) {
        return toJSONString(object, true);
    }

    default String toJSONString(Object object, boolean prettyPrinter) {
        return toJSONString(object, null, prettyPrinter);
    }

    default String toJSONString(Object object, Class<?> viewClass) {
        return toJSONString(object, viewClass, false);
    }

    default String toPrettyJSONString(Object object, Class<?> viewClass) {
        return toJSONString(object, viewClass, true);
    }

    default byte[] toJSONBytes(Object object) {
        return toJSONBytes(object, null);
    }

    String toJSONString(Object object, Class<?> viewClass, boolean prettyPrinter);

    byte[] toJSONBytes(Object object, Class<?> viewClass);

    void writeValue(File out, Object object, OpenOption... options) throws IOException;

    void writeValue(OutputStream output, Object object) throws IOException;

    void writeValue(OutputStream output, Object object, boolean prettyPrinter) throws IOException;

    // READ value API

    /**
     * 将给定的map转换为目标类型的对象。
     *
     * @param map 要转换的map。
     * @param targetClass 目标对象类型。
     * @param <T> 目标对象泛型
     * @return 返回转换后的java bean。
     */
    <T> T convert(Map<String, Object> map, Class<T> targetClass);

    @SuppressWarnings("TypeParameterUnusedInFormals")
    <T> T convert(Map<String, Object> map, Type type);

    /**
     * 解析指定的JSON格式字符串，并转换为指定的目标类型对象。
     *
     * @param jsonString 要解析的JSON字符串。
     * @param targetClass 要转换的目标类型。
     * @param <T> 目标类型泛型
     * @return 给定JSON字符串转换的对象。
     * @throws JsonParseException 如果JSON字符串解析失败。
     */
    @Contract("null, _ -> null; _, null -> fail")
    <T> T parseObject(String jsonString, Class<T> targetClass);

    @SuppressWarnings("TypeParameterUnusedInFormals")
    <T> T parseObject(String jsonString, Type type);

    <T> T parseObject(File file, Class<T> targetClass) throws IOException;

    @SuppressWarnings("TypeParameterUnusedInFormals")
    <T> T parseObject(File file, Type targetType) throws IOException;

    <T> T parseObject(InputStream input, Class<T> targetClass) throws IOException;

    @SuppressWarnings("TypeParameterUnusedInFormals")
    <T> T parseObject(InputStream input, Type targetType) throws IOException;

    default <T> List<T> parseToList(String jsonString, Class<T> elementClass) {
        Class<List<T>> listClass = Generics.listClass(elementClass);
        return parseToCollection(jsonString, listClass, elementClass);
    }

    @SuppressWarnings("unchecked")
    default <T> List<T> parseToList(String jsonString, Type elementType) {
        return parseToCollection(jsonString, Generics.listClass(elementType), elementType);
    }

    default <T> Set<T> parseToSet(String jsonString, Class<T> elementClass) {
        return parseToCollection(jsonString, Generics.setClass(elementClass), elementClass);
    }

    default <T> Set<T> parseToSet(String jsonString, Type elementType) {
        return parseToCollection(jsonString, Generics.setClass(elementType), elementType);
    }

    <C extends Collection<T>, T> C parseToCollection(String jsonString, Class<C> listClass, Class<T> elementClass);

    <C extends Collection<T>, T> C parseToCollection(String jsonString, Class<C> colClass, Type elementType);

    default Map<String, Object> parseToMap(String jsonString) {
        return parseToMap(jsonString, String.class, Object.class);
    }

    default <K, V> Map<K, V> parseToMap(String jsonString, Class<K> keyClass, Class<V> valueClass) {
        return parseToMap(jsonString, Generics.mapClass(keyClass, valueClass), keyClass, valueClass);
    }

    <K, V> Map<K, V> parseToMap(String jsonString, Type keyType, Type valueType);

    <K, V, M extends Map<K, V>> M parseToMap(String jsonString, Class<M> mapClass, Class<K> keyClass, Class<V> valueClass);
}
